package com.nulldev.util.web.YouTubeExtractor.video;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import com.nulldev.util.concurrency.threadIt.v4.emapi.uft.Executable;
import com.nulldev.util.manage.MarkedForRemoval;
import com.nulldev.util.manage.NonStandard;
import com.nulldev.util.web.YouTubeExtractor.advertising.YTEAdvertisingMetadata;
import com.nulldev.util.web.YouTubeExtractor.comments.YTComments.YTCommentInitData;
import com.nulldev.util.web.YouTubeExtractor.extractors.util.YTIAPIClientType;
import com.nulldev.util.web.YouTubeExtractor.metadata.YouTubeMetadata;
import com.nulldev.util.web.YouTubeExtractor.playlist.Playlist;

public class ExtractedVideo {
	private final List<YouTubeVideo> videos;
	private final YouTubeMetadata metadata;
	private final ExtractionResult result;
	private String resultMessageID;
	private String youtubeMessageID;
	private Playlist playlist;
	private YTCommentInitData ytcid;
	private String live_chat_url;
	@Deprecated
	private volatile boolean enableDashStreamMode;

	public ExtractedVideo(final List<YouTubeVideo> videos, final YouTubeMetadata meta, final ExtractionResult result) {
		this.videos = videos;
		this.metadata = meta;
		this.result = result;
	}

	public List<YouTubeVideo> videos() {
		return this.videos;
	}

	public YouTubeVideo video(final int itag) {
		return this.videos.stream().filter((video) -> video.getTag() == itag).findFirst().get();
	}

	public List<YouTubeVideo> getVideos() {
		return this.videos;
	}

	public ExtractionResult getResult() {
		return this.result;
	}

	public YouTubeMetadata getMetadata() {
		return this.metadata;
	}

	public boolean hasIDInfo() {
		return this.resultMessageID != null;
	}

	public String getIDInfo() {
		return this.resultMessageID;
	}

	public ExtractedVideo setMessage(final String id) {
		this.resultMessageID = id;
		return this;
	}

	public boolean hasYTInfo() {
		return this.youtubeMessageID != null;
	}

	public String getYTInfo() {
		return this.youtubeMessageID;
	}

	public ExtractedVideo setYTMessage(final String msg) {
		this.youtubeMessageID = msg;
		return this;
	}

	public ExtractedVideo setPlaylist(final Playlist playlist) {
		this.playlist = playlist;
		return this;
	}

	public boolean hasPlaylist() {
		return this.playlist != null;
	}

	public Playlist getPlaylist() {
		return this.playlist;
	}

	@NonStandard
	public void clear() {
		if (this.videos != null) {
			this.videos.clear();
		}
		if (this.hasPlaylist()) {
			this.playlist.get().clear();
		}
		if (this.metadata != null) {
			this.metadata.clear();
		}
	}

	public ExtractedVideo setCommentInitData(final YTCommentInitData ytCommentInitData) {
		this.ytcid = ytCommentInitData;
		return this;
	}

	public boolean hasCommentData() {
		return this.ytcid != null;
	}

	public YTCommentInitData getCommentData() {
		return this.ytcid;
	}

	public boolean hasChatPayload() {
		return this.live_chat_url != null;
	}

	public String getChatPayload() {
		return this.live_chat_url;
	}

	public ExtractedVideo setChatPayload(final String live_chat_url) {
		this.live_chat_url = live_chat_url;
		return this;
	}

	@Deprecated
	@MarkedForRemoval(reason = "YoutubeVideo's DASH_FORMAT is a better solution.")
	public boolean isDashStreamMode() {
		return this.enableDashStreamMode;
	}

	@Deprecated
	public ExtractedVideo enableDashStreamMode(final boolean value) {
		this.enableDashStreamMode = value;
		return this;
	}

	/* ABI(5100) */

	private boolean supportsLateExtraction;
	private Executable<?> lateExtractionHold;

	public void awaitCompletion() {
		if (this.lateExtractionHold != null && this.supportsLateExtraction)
			this.lateExtractionHold.waitTillCompletion();
	}

	public void awaitCompletionFor(final long amount, final TimeUnit unit) {
		if (this.lateExtractionHold != null && this.supportsLateExtraction)
			this.lateExtractionHold.waitFor(amount, unit);
	}

	public boolean supportsLateExtraction() {
		return this.supportsLateExtraction;
	}

	public ExtractedVideo setLateExtraction(final boolean value) {
		this.supportsLateExtraction = value;
		return this;
	}

	public ExtractedVideo setLateExtractionHold(final Executable<?> hold) {
		if (hold != null)
			this.lateExtractionHold = hold;
		return this;
	}

	public Executable<?> getLateHold() {
		return this.lateExtractionHold;
	}

	/* */

	@Override
	public String toString() {
		return "ExtractedVideo[result=" + result + ",late=" + (this.supportsLateExtraction && this.lateExtractionHold != null) + ",videos=" + videos
				+ ",message=" + resultMessageID + ",subMessage=" + youtubeMessageID + "]";
	}

	/* ABI(5500) */

	private final AtomicReference<YTIAPIClientType> clientType = new AtomicReference<YTIAPIClientType>();

	public boolean hasClientType() {
		return this.clientType.get() != null;
	}

	public YTIAPIClientType getClientType() {
		return this.clientType.get();
	}

	public ExtractedVideo setClientType(final YTIAPIClientType clientType) {
		this.clientType.set(clientType);
		return this;
	}

	/* ABI(6090) */

	private final AtomicReference<YTEAdvertisingMetadata> adMetadata = new AtomicReference<YTEAdvertisingMetadata>();

	public boolean hasAdvertisingMetadata() {
		return this.adMetadata.get() != null;
	}

	public YTEAdvertisingMetadata getAdvertisingMetadata() {
		return this.adMetadata.get();
	}

	public ExtractedVideo setAdvertisingMetadata(final YTEAdvertisingMetadata metadata) {
		this.adMetadata.set(metadata);
		return this;
	}
}
